package com.ok.common.base

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.viewbinding.ViewBinding
import com.ok.common.common.Constants
import com.ok.common.R
import com.ok.common.utils.EventUtils
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.reflect.ParameterizedType

abstract class BaseFragment<VB : ViewBinding> : Fragment(), View.OnClickListener {

    private var _binding: VB? = null

    protected val mBinding get() = _binding!!

    protected var mActivity: BaseActivity<*>? = null

    private var isFirst = true

    private var lastButtonId = -1

    private var lastClickTime = 0L

    private var isViewCreated = false

    private var isVisibleToUser = false

    @LayoutRes
    protected open val layoutId = 0

    override fun onAttach(context: Context) {
        super.onAttach(context)
        mActivity = getBaseActivity()
    }

    open fun getBaseActivity(): BaseActivity<*>? {
        return this.activity as BaseActivity<*>?
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        if (isRegisterEvent) {
            EventUtils.register(this)
        }
        isViewCreated = true
        return initBinding(inflater, container)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        initView(arguments)
        initImmersionBar()
        initObserve()
        initData()
        initListener()
    }

    abstract fun initView(args: Bundle?)

    open fun initImmersionBar() {
//        immersionBar()
    }

    open fun initData() {}

    open fun initListener() {}

    open fun initObserve() {}

    open fun lazyLoad() {}

    //防止多次点击的点击事件
    open fun mClick(v: View?) {}

    override fun onResume() {
        super.onResume()
        isVisibleToUser = true
        if (isViewCreated && isVisibleToUser) {
            lazyLoad()
        }
    }

    override fun onPause() {
        super.onPause()
        isVisibleToUser = false
    }

    open var isRegisterEvent = false

    @Subscribe(threadMode = ThreadMode.MAIN)
    open fun onEventBusCome(event: BaseEvent?) {
        if (event != null) {
            handleEvent(event)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    open fun onStickyEventBusCome(event: BaseEvent?) {
        if (event != null) {
            handleStickyEvent(event)
        }
    }

    open fun handleEvent(event: BaseEvent) {}

    open fun handleStickyEvent(event: BaseEvent) {}

    protected fun showLoading(text: String = getString(R.string.loading)) {
        getBaseActivity()?.showLoading(text)
    }

    protected fun dismissLoading() {
        getBaseActivity()?.dismissLoading()
    }

    fun finish() {
        mActivity?.finish()
    }

    override fun onClick(v: View?) {
        val currentButtonId = v?.id
        if (!fastClick() && (lastButtonId == currentButtonId)) {
            return
        }
        if (currentButtonId != null) {
            lastButtonId = currentButtonId
        }
        mClick(v)
    }

    private fun fastClick(): Boolean {
        if (System.currentTimeMillis() - lastClickTime <= Constants.MIN_CLICK_DELAY_TIME) {
            return false
        }
        lastClickTime = System.currentTimeMillis()
        return true
    }

    private fun initBinding(inflater: LayoutInflater, container: ViewGroup?): View {
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val cls = type.actualTypeArguments.map { it as Class<*> }
                .first { ViewBinding::class.java.isAssignableFrom(it) }
            return when {
                ViewDataBinding::class.java.isAssignableFrom(cls) && cls != ViewDataBinding::class.java -> {
                    if (layoutId == 0) throw IllegalArgumentException("Using DataBinding requires overriding method layoutId")
                    _binding = DataBindingUtil.inflate(inflater, layoutId, container, false)
                    (mBinding as ViewDataBinding).lifecycleOwner = this
                    mBinding.root
                }

                ViewBinding::class.java.isAssignableFrom(cls) && cls != ViewBinding::class.java -> {
                    cls.getDeclaredMethod("inflate", LayoutInflater::class.java).let {
                        @Suppress("UNCHECKED_CAST")
                        _binding = it.invoke(null, inflater) as VB
                        mBinding.root
                    }
                }

                else -> {
                    if (layoutId == 0) throw IllegalArgumentException("If you don't use ViewBinding, you need to override method layoutId")
                    inflater.inflate(layoutId, container, false)
                }
            }
        } else throw IllegalArgumentException("Generic error")
    }

    override fun onDestroy() {
        super.onDestroy()
        if (isRegisterEvent) {
            EventUtils.unregister(this)
        }
    }

}